home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / multispheremap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  18.5 KB  |  738 lines

  1. #include <assert.h>
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <GL/glut.h>
  6. #include "texture.h"
  7.  
  8. /* Some <math.h> files do not define M_PI... */
  9. #ifndef M_PI
  10. #define M_PI 3.14159265358979323846
  11. #endif
  12.  
  13. #ifndef __sgi
  14. #define trunc(x) ((double)((int)(x)))
  15. #endif
  16.  
  17. GLUquadricObj *cone, *base, *qsphere;
  18.  
  19. static char defaultFile[] = "data/mandrill256.rgb";
  20. GLuint floorList;
  21.  
  22. GLboolean animate = 1, useSphereMaps = 1;
  23.  
  24. GLsizei w = 256, h = 256;
  25.  
  26. #define LEFT     3
  27. #define RIGHT     1
  28. #define FRONT    2
  29. #define BACK    0
  30. #define TOP    4
  31. #define BOTTOM     5
  32.  
  33. GLuint *faceMap[6];
  34. GLsizei faceW = 128;
  35.  
  36. GLuint *sphereMap[2];
  37. GLuint sphereW = 256;
  38.  
  39. GLfloat angle1[6] = {90, 180, 270, 0, 90, -90};
  40. GLfloat axis1[6][3] = {{0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {1,0,0}, {1,0,0}};
  41. GLfloat angle2[6] = {0, 0, 0, 0, 180, 180};
  42. GLfloat axis2[6][3] = {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,1,0}, {0,1,0}};
  43.  
  44. #define TORUS_BIT    1
  45. #define SPHERE_BIT    2
  46.  
  47. void reset_textures(void)
  48. {
  49.   unsigned int i;
  50.  
  51.   /* make sphereMap[0] start out all red... */
  52.   for (i = 0; i < sphereW*sphereW; i++) sphereMap[0][i] = 0xff0000ff;
  53.   /* make sphereMap[1] start out all green... */
  54.   for (i = 0; i < sphereW*sphereW; i++) sphereMap[1][i] = 0x00ff00ff;
  55. }
  56.  
  57. void realloc_textures(void)
  58. {
  59.   static int first = 1;
  60.   int i;
  61.  
  62.   if (!first) {
  63.     for (i = 0; i < 6; i++) free(faceMap[i]);
  64.   } else {
  65.     first = 0;
  66.   }
  67.  
  68.   for (i = 0; i < 6; i++) {
  69.     faceMap[i] = (GLuint *)malloc(faceW*faceW*sizeof(GLuint));
  70.     if (!faceMap[i]) {
  71.       fprintf(stderr, "malloc of %d bytes failed.\n", 
  72.           faceW*faceW*sizeof(GLuint));
  73.     }
  74.   }
  75.  
  76.   sphereMap[0] = (GLuint *)malloc(sphereW * sphereW * sizeof(GLuint));
  77.   sphereMap[1] = (GLuint *)malloc(sphereW * sphereW * sizeof(GLuint));
  78.   reset_textures();
  79. }
  80.  
  81. void eliminate_alpha(GLsizei w, GLsizei h, GLuint *map)
  82. {
  83.   int x, y;
  84.  
  85.   /* top & bottom rows */
  86.   for (x = 0; x < w; x++) {
  87.     map[x] &= 0xffffff00;
  88.     map[x + (h-1)*w] &= 0xffffff00;
  89.   }
  90.  
  91.   for (y = 0; y < h; y++) {
  92.     map[y*w] &= 0xffffff00;
  93.     map[y*w + (w-1)] &= 0xffffff00;
  94.   }
  95. }
  96.  
  97. void init(const char *fname)
  98. {
  99.   GLuint *img;
  100.   GLsizei w, h;
  101.   int comps;
  102.  
  103.   glEnable(GL_DEPTH_TEST); 
  104.   glEnable(GL_CULL_FACE); 
  105.  
  106.   cone = gluNewQuadric();
  107.   base = gluNewQuadric();
  108.   qsphere = gluNewQuadric();
  109.  
  110.   img = read_texture(fname, &w, &h, &comps);
  111.   if (!img) {
  112.     fprintf(stderr, "Could not open %s\n", fname);
  113.     exit(1);
  114.   }
  115.   floorList = glGenLists(1);
  116.   glNewList(floorList, GL_COMPILE);
  117.   glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, 
  118.            GL_RGBA, GL_UNSIGNED_BYTE, img);
  119.   glEndList();
  120.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  121.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  122.   free(img);
  123.  
  124.   glClearColor(.25, .25, .5, 1.0);
  125.  
  126.   realloc_textures();
  127. }
  128.  
  129. void reshape(GLsizei winW, GLsizei winH) 
  130. {
  131.   w = winW/2;
  132.  
  133.   glViewport(0, 0, w, h);
  134.   
  135.   glMatrixMode(GL_PROJECTION);
  136.   glLoadIdentity();
  137.   gluPerspective(60, 1, .01, 10);
  138.   gluLookAt(-1, 0, 2.577, 0, 0, -5, 0, 1, 0);
  139.   
  140.   glMatrixMode(GL_MODELVIEW);
  141.   glLoadIdentity();
  142. }
  143.  
  144. void draw_room(void)
  145. {
  146.   /* material for the walls, floor, ceiling */
  147.   static GLfloat wallMat[] = {1.f, 1.f, 1.f, 1.f};
  148.  
  149.   glPushMatrix();
  150.   glScalef(3, 2, 3);
  151.  
  152.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wallMat);
  153.  
  154.   /* floor, textured */
  155.   glColor3f(1, 1, 1);
  156.   glEnable(GL_TEXTURE_2D);
  157.   glCallList(floorList);
  158.   glBegin(GL_QUADS);
  159.   glNormal3f(0, 1, 0);
  160.   glTexCoord2f(0, 0);
  161.   glVertex3f(-1, -1, 1);
  162.   glTexCoord2f(1, 0);
  163.   glVertex3f(1, -1, 1);
  164.   glTexCoord2f(1, 1);
  165.   glVertex3f(1, -1, -1);
  166.   glTexCoord2f(0, 1);
  167.   glVertex3f(-1, -1, -1);
  168.   glEnd();
  169.   glDisable(GL_TEXTURE_2D);
  170.  
  171.   /* ceiling */
  172.   glColor3f(wallMat[0] * 1., wallMat[1] * 1., wallMat[2] * 1.);
  173.   glBegin(GL_QUADS);
  174.   glNormal3f(0, -1, 0);
  175.   glVertex3f(-1, 1, -1);
  176.   glVertex3f(1, 1, -1);
  177.   glVertex3f(1, 1, 1);
  178.   glVertex3f(-1, 1, 1);  
  179.  
  180.   /* left wall */
  181.   glColor3f(wallMat[0] * .75, wallMat[1] * .75, wallMat[2] * .75);
  182.   glNormal3f(1, 0, 0);
  183.   glVertex3f(-1, -1, -1);
  184.   glVertex3f(-1, 1, -1);
  185.   glVertex3f(-1, 1, 1);
  186.   glVertex3f(-1, -1, 1);
  187.  
  188.   /* right wall */
  189.   glColor3f(wallMat[0] * .25, wallMat[1] * .25, wallMat[2] * .25);
  190.   glNormal3f(-1, 0, 0);
  191.   glVertex3f(1, -1, 1);
  192.   glVertex3f(1, 1, 1);
  193.   glVertex3f(1, 1, -1);
  194.   glVertex3f(1, -1, -1);
  195.  
  196.   /* far wall */
  197.   glColor3f(wallMat[0] * .5, wallMat[1] * .5, wallMat[2] * .5);
  198.   glNormal3f(0, 0, 1);
  199.   glVertex3f(-1, -1, -1);
  200.   glVertex3f(1, -1, -1);
  201.   glVertex3f(1, 1, -1);
  202.   glVertex3f(-1, 1, -1);
  203.  
  204.   /* back wall */
  205.   glColor3f(wallMat[0] * .5, wallMat[1] * .5, wallMat[2] * .5);
  206.   glNormal3f(0, 0, -1);
  207.   glVertex3f(-1, 1, 1);
  208.   glVertex3f(1, 1, 1);
  209.   glVertex3f(1, -1, 1);
  210.   glVertex3f(-1, -1, 1);
  211.  
  212.   glEnd();
  213.  
  214.   glPopMatrix();
  215. }
  216.  
  217. void draw_cone(void)
  218. {
  219.   static GLfloat cone_mat[] = {0.f, .5f, 1.f, 1.f};
  220.  
  221.   glPushMatrix();
  222.   glTranslatef(0, -1, 0);
  223.   glRotatef(-90, 1, 0, 0);
  224.  
  225.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
  226.   
  227.   /* base is coplanar with floor, so turn off depth testing */
  228.   glDisable(GL_DEPTH_TEST);
  229.   gluDisk(base, 0., .3, 20, 1); 
  230.   glEnable(GL_DEPTH_TEST);
  231.  
  232.   gluCylinder(cone, .3, 0, 1.25, 20, 1);
  233.  
  234.   glPopMatrix();
  235. }
  236.  
  237. void draw_cube(void)
  238. {
  239.   glBegin(GL_QUADS);
  240.  
  241.   glNormal3f(0, -1, 0);
  242.   glVertex3f(-.25, -.25, -.25);
  243.   glVertex3f(.25, -.25, -.25);
  244.   glVertex3f(.25, -.25, .25);
  245.   glVertex3f(-.25, -.25, .25);
  246.  
  247.   glNormal3f(0, 1, 0);
  248.   glVertex3f(-.25, .25, .25);  
  249.   glVertex3f(.25, .25, .25);
  250.   glVertex3f(.25, .25, -.25);
  251.   glVertex3f(-.25, .25, -.25);
  252.  
  253.   glNormal3f(1, 0, 0);
  254.   glVertex3f(.25, -.25, -.25);
  255.   glVertex3f(.25, .25, -.25);
  256.   glVertex3f(.25, .25, .25);
  257.   glVertex3f(.25, -.25, .25);
  258.  
  259.   glNormal3f(-1, 0, 0);
  260.   glVertex3f(-.25, -.25, .25);
  261.   glVertex3f(-.25, .25, .25);
  262.   glVertex3f(-.25, .25, -.25);
  263.   glVertex3f(-.25, -.25, -.25);
  264.  
  265.   glNormal3f(0, 0, -1);
  266.   glVertex3f(-.25, .25, -.25);
  267.   glVertex3f(.25, .25, -.25);
  268.   glVertex3f(.25, -.25, -.25);
  269.   glVertex3f(-.25, -.25, -.25);
  270.  
  271.   glNormal3f(0, 0, 1);
  272.   glVertex3f(-.25, -.25, .25);
  273.   glVertex3f(.25, -.25, .25);
  274.   glVertex3f(.25, .25, .25);
  275.   glVertex3f(-.25, .25, .25);
  276.  
  277.   glEnd();
  278. }
  279.  
  280. void draw_sphere(GLdouble angle)
  281. {
  282.   static GLfloat sphere_mat[] = {.2f, .7f, .2f, 1.f};
  283.  
  284.   glTexImage2D(GL_TEXTURE_2D, 0, 4, sphereW, sphereW, 0,
  285.            GL_RGBA, GL_UNSIGNED_BYTE, sphereMap[1]);
  286.   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  287.   
  288.   if (useSphereMaps) glEnable(GL_TEXTURE_2D);
  289.  
  290.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  291.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  292.   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  293.   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  294.   glEnable(GL_TEXTURE_GEN_S);
  295.   glEnable(GL_TEXTURE_GEN_T);
  296.  
  297.   glPushMatrix();
  298.   glRotatef(45, 0, 0, 1);
  299.   glRotatef(angle, 0, 1, 0);
  300.   glTranslatef(1, 0, 0);
  301.  
  302.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
  303.   glColor3fv(sphere_mat);
  304. #if 1
  305.   {
  306.     GLUquadricObj *sphere = gluNewQuadric();
  307.     gluSphere(sphere, .6, 64, 64);
  308.     gluDeleteQuadric(sphere);
  309.   }
  310. #else
  311.   draw_cube();
  312. #endif
  313.  
  314.   glPopMatrix();
  315.  
  316.   glDisable(GL_TEXTURE_GEN_S);
  317.   glDisable(GL_TEXTURE_GEN_T);
  318.   glDisable(GL_TEXTURE_2D);
  319. }
  320.  
  321. void draw_torus(GLdouble angle)
  322. {
  323.   angle = 0;
  324.  
  325.   glTexImage2D(GL_TEXTURE_2D, 0, 4, sphereW, sphereW, 0,
  326.            GL_RGBA, GL_UNSIGNED_BYTE, sphereMap[0]);
  327.   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  328.  
  329.   if (useSphereMaps) glEnable(GL_TEXTURE_2D);  
  330.  
  331.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  332.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  333.   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  334.   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  335.   glEnable(GL_TEXTURE_GEN_S);
  336.   glEnable(GL_TEXTURE_GEN_T);
  337.  
  338.   glColor3f(1, .5, .5);
  339.  
  340.   glPushMatrix();
  341.   glRotatef(angle, 1, 0, 0);
  342.   glRotatef(0, 0, 1, 0);
  343.  
  344. #if 0
  345.   glutSolidTorus(.2, .25, 32, 32);
  346. #else
  347.   {
  348.     GLUquadricObj *sphere = gluNewQuadric();
  349.     gluSphere(sphere, .2, 64, 64);
  350.   }
  351. #endif
  352.  
  353.   glPopMatrix();
  354.  
  355.   glDisable(GL_TEXTURE_GEN_S);
  356.   glDisable(GL_TEXTURE_GEN_T);
  357.   glDisable(GL_TEXTURE_2D);
  358. }
  359.  
  360. void draw_scene(GLdouble degrees, GLint bits)
  361. {
  362.   glEnable(GL_CULL_FACE);
  363.   draw_room();
  364.  
  365.   if (bits & TORUS_BIT) draw_torus(degrees); 
  366.   if (bits & SPHERE_BIT) draw_sphere(degrees);
  367. }
  368.  
  369. GLdouble get_secs(void)
  370. {
  371.   return glutGet(GLUT_ELAPSED_TIME) / 1000.0;
  372. }
  373.  
  374. void draw_special_sphere(int tess)
  375. {
  376.   float r = 1.0, r1, r2, z1, z2;
  377.   float theta, phi;
  378.   int nlon = tess, nlat = tess;
  379.   int i, j;
  380.  
  381.   glBegin(GL_TRIANGLE_FAN);
  382.   theta = M_PI*1.0/nlat;
  383.   r2 = r*sin(theta); z2 = r*cos(theta);
  384.   glNormal3f(0.0, 0.0, 1.0);
  385.   glVertex4f(0.0, 0.0, r*r, r);
  386.   for (j = 0, phi = 0.0; j <= nlon; j++, phi = 2*M_PI*j/nlon) {
  387.     glNormal3f(r2*cos(phi), r2*sin(phi), z2);
  388.     glVertex4f(r2*cos(phi)*z2, r2*sin(phi)*z2, z2*z2, z2); /* top */
  389.   }
  390.   glEnd();
  391.  
  392.   for (i = 2; i < nlat; i++) {
  393.     theta = M_PI*i/nlat;
  394.     r1 = r*sin(M_PI*(i-1)/nlat); z1 = r*cos(M_PI*(i-1)/nlat);
  395.     r2 = r*sin(theta); z2 = r*cos(theta);
  396.  
  397.     if (fabs(z1) < 0.01 || fabs(z2) < 0.01)
  398.       break;
  399.  
  400.     glBegin(GL_QUAD_STRIP);
  401.     for (j = 0, phi = 0; j <= nlat; j++, phi = 2*M_PI*j/nlon) {
  402.       glNormal3f(r1*cos(phi), r1*sin(phi), z1);
  403.       glVertex4f(r1*cos(phi)*z1, r1*sin(phi)*z1, z1*z1, z1);
  404.       glNormal3f(r2*cos(phi), r2*sin(phi), z2);
  405.       glVertex4f(r2*cos(phi)*z2, r2*sin(phi)*z2, z2*z2, z2);
  406.     }
  407.     glEnd();
  408.   }
  409. }
  410.  
  411. void render_spheremap(void)
  412. {
  413.   GLfloat p[4];
  414.   int i;
  415.  
  416.   glColor4f(1, 1, 1, 1);
  417.  
  418. #if 1
  419.   glEnable(GL_TEXTURE_2D);
  420. #endif
  421.  
  422.   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  423.  
  424.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  425.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  426.  
  427.   glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  428.  
  429.   p[0] = 2.0; p[1] = p[2] = p[3] = 0.0; /* 2zx */
  430.   glTexGenfv(GL_S, GL_OBJECT_PLANE, p);
  431.   
  432.   glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  433.   p[0] = 0.0; p[1] = 2.0; p[2] = p[3] = 0.0; /* 2zy */
  434.   glTexGenfv(GL_T, GL_OBJECT_PLANE, p);
  435.   
  436.   glTexGenf(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  437.   p[0] = p[1] = 0.0; p[2] = 0.0; p[3] = 2.0; /* 2z */
  438.   glTexGenfv(GL_R, GL_OBJECT_PLANE, p);
  439.  
  440.   glEnable(GL_TEXTURE_GEN_S);
  441.   glEnable(GL_TEXTURE_GEN_T);
  442.   glEnable(GL_TEXTURE_GEN_R);
  443.   
  444.   glMatrixMode(GL_PROJECTION);
  445.   glPushMatrix();
  446.   glMatrixMode(GL_MODELVIEW);
  447.   glPushMatrix();
  448.   glMatrixMode(GL_TEXTURE);
  449.   glPushMatrix();
  450.  
  451.   glMatrixMode(GL_PROJECTION);
  452.   glLoadIdentity();
  453.   glOrtho(-.98, .98, -.98, .98, 1.0, 100);
  454.   glMatrixMode(GL_MODELVIEW);
  455.   glLoadIdentity();
  456.   gluLookAt(0, 0, 6,
  457.         0, 0, 0,
  458.         0, 1, 0);
  459.  
  460.   glEnable(GL_DEPTH_TEST);
  461.   glEnable(GL_CULL_FACE);
  462.  
  463.   glEnable(GL_BLEND);
  464.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  465.  
  466. #if 1
  467.   glClearColor(0.25, 0.25, 0.5, 1.0);
  468.   glClearDepth(1.0);
  469.   glClear(/* GL_COLOR_BUFFER_BIT | */GL_DEPTH_BUFFER_BIT);
  470. #endif
  471.  
  472.   for (i = 0; i < 6; i++) {
  473.     glTexImage2D(GL_TEXTURE_2D, 0, 4, faceW, faceW, 0, 
  474.          GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)faceMap[i]);
  475.  
  476.     glMatrixMode(GL_TEXTURE);
  477.     glLoadIdentity();
  478.     glScalef(0.5, 0.5, 1.0);
  479.     glTranslatef(1.0, 1.0, 0.0);
  480.     glFrustum(-1.01, 1.01, -1.01, 1.01, 1.0, 100.0);
  481.     if (angle2[i]) {
  482.       glRotatef(angle2[i], axis2[i][0], axis2[i][1], axis2[i][2]);
  483.     }
  484.     glRotatef(angle1[i], axis1[i][0], axis1[i][1], axis1[i][2]);
  485.     
  486.     /* XXX atul does another angle thing here... */
  487.     /* XXX atul does a third angle thing here... */
  488.     
  489.     glTranslatef(0.0, 0.0, -1.00);
  490.     
  491.     glMatrixMode(GL_MODELVIEW);
  492.     glClear(GL_DEPTH_BUFFER_BIT);
  493.     draw_special_sphere(20);
  494.   }
  495.  
  496.   glDisable(GL_BLEND);
  497.   glDisable(GL_CULL_FACE);
  498.  
  499.   glMatrixMode(GL_PROJECTION);
  500.   glPopMatrix();
  501.   glMatrixMode(GL_MODELVIEW);
  502.   glPopMatrix();
  503.   glMatrixMode(GL_TEXTURE);
  504.   glPopMatrix();
  505.  
  506.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  507.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  508.  
  509.   glDisable(GL_TEXTURE_GEN_S);
  510.   glDisable(GL_TEXTURE_GEN_T);
  511.   glDisable(GL_TEXTURE_GEN_R);
  512.  
  513.   glDisable(GL_TEXTURE_2D);
  514. }
  515.  
  516. void make_projection(int face, GLfloat xpos, GLfloat ypos, GLfloat zpos)
  517. {
  518.   glMatrixMode(GL_PROJECTION);
  519.   glLoadIdentity();
  520.   gluPerspective(90, 1, .01, 10);
  521.   if (angle2[face]) {
  522.       glRotatef(angle2[face], axis2[face][0], axis2[face][1], axis2[face][2]);
  523.     }
  524.   glRotatef(angle1[face], axis1[face][0], axis1[face][1], axis1[face][2]);
  525.   gluLookAt(xpos, ypos, zpos,
  526.         ypos, ypos, zpos - 1,
  527.         0, 1, 0);
  528.   glMatrixMode(GL_MODELVIEW);
  529.   glLoadIdentity();
  530. }
  531.  
  532. void draw(void)
  533. {
  534.   static int frame = 0;
  535.   GLenum err;
  536.   GLdouble secs;
  537.   static double degrees = 0;
  538.   GLfloat sphereX, sphereY, sphereZ;
  539.   
  540.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  541.   
  542.   /* one revolution every 10 seconds... */
  543.   if (animate) {
  544.     secs = get_secs();
  545.     secs = secs - 10.*trunc(secs / 10.);
  546.     degrees = (secs/10.) * (360.);
  547.   }
  548.   
  549.   if (frame == 0) {
  550.     /* switch the viewport and draw the faces of the cube from the 
  551.      * point of view of the square... */
  552.   
  553.     glViewport(w + 0*faceW, 0, faceW, faceW);
  554.     make_projection(LEFT, 0, 0, 0);
  555.     draw_scene(degrees, -1 & ~TORUS_BIT);
  556.     glReadPixels(w + 0*faceW, 0, faceW, faceW, 
  557.          GL_RGBA, GL_UNSIGNED_BYTE, faceMap[LEFT]);
  558.     eliminate_alpha(faceW, faceW, faceMap[LEFT]);
  559.  
  560.     glViewport(w + 1*faceW, 0, faceW, faceW);
  561.     make_projection(RIGHT, 0, 0, 0);
  562.     draw_scene(degrees, -1 & ~TORUS_BIT);
  563.     glReadPixels(w + 1*faceW, 0, faceW, faceW, 
  564.          GL_RGBA, GL_UNSIGNED_BYTE, faceMap[RIGHT]);
  565.     eliminate_alpha(faceW, faceW, faceMap[RIGHT]);
  566.  
  567.     glViewport(w + 2*faceW, 0, faceW, faceW);
  568.     make_projection(BOTTOM, 0, 0, 0);
  569.     draw_scene(degrees, -1 & ~TORUS_BIT);
  570.     glReadPixels(w + 2*faceW, 0, faceW, faceW, 
  571.          GL_RGBA, GL_UNSIGNED_BYTE, faceMap[BOTTOM]);
  572.     eliminate_alpha(faceW, faceW, faceMap[BOTTOM]);
  573.  
  574.     glViewport(w + 0*faceW, faceW, faceW, faceW);
  575.     make_projection(TOP, 0, 0, 0);
  576.     draw_scene(degrees, -1 & ~TORUS_BIT);
  577.     glReadPixels(w + 0*faceW, faceW, faceW, faceW, 
  578.          GL_RGBA, GL_UNSIGNED_BYTE, faceMap[TOP]);
  579.     eliminate_alpha(faceW, faceW, faceMap[TOP]);
  580.  
  581.     glViewport(w + 1*faceW, faceW, faceW, faceW);
  582.     make_projection(FRONT, 0, 0, 0);
  583.     draw_scene(degrees, -1 & ~TORUS_BIT);
  584.     glReadPixels(w + 1*faceW, faceW, faceW, faceW, 
  585.          GL_RGBA, GL_UNSIGNED_BYTE, faceMap[FRONT]);
  586.     eliminate_alpha(faceW, faceW, faceMap[FRONT]);
  587.  
  588.     glViewport(w + 2*faceW, faceW, faceW, faceW);
  589.     make_projection(BACK, 0, 0, 0);
  590.     draw_scene(degrees, -1 & ~TORUS_BIT);
  591.     glReadPixels(w + 2*faceW, faceW, faceW, faceW, 
  592.          GL_RGBA, GL_UNSIGNED_BYTE, faceMap[BACK]);
  593.     eliminate_alpha(faceW, faceW, faceMap[BACK]);
  594.  
  595.     /* create the sphere map for the cube... */
  596.     glViewport(w, 2*faceW, sphereW, sphereW);
  597.     render_spheremap();
  598.     glReadPixels(w, 2*faceW, sphereW, sphereW, GL_RGBA, GL_UNSIGNED_BYTE,
  599.          sphereMap[0]);
  600.   } else {
  601.     sphereX = 
  602.     sphereY = cos((degrees/360.) * 2.*M_PI);
  603.     sphereZ = -sin((degrees/360.) * 2.*M_PI);
  604.  
  605.     glViewport(w + 0*faceW, 0, faceW, faceW);
  606.     make_projection(LEFT, sphereX, sphereY, sphereZ);
  607.     draw_scene(degrees, -1 & ~SPHERE_BIT);
  608.     glReadPixels(w + 0*faceW, 0, faceW, faceW, 
  609.          GL_RGBA, GL_UNSIGNED_BYTE, faceMap[LEFT]);
  610.     eliminate_alpha(faceW, faceW, faceMap[LEFT]);
  611.  
  612.     glViewport(w + 1*faceW, 0, faceW, faceW);
  613.     make_projection(RIGHT, sphereX, sphereY, sphereZ);
  614.     draw_scene(degrees, -1 & ~SPHERE_BIT);
  615.     glReadPixels(w + 1*faceW, 0, faceW, faceW, 
  616.          GL_RGBA, GL_UNSIGNED_BYTE, faceMap[RIGHT]);
  617.     eliminate_alpha(faceW, faceW, faceMap[RIGHT]);
  618.  
  619.     glViewport(w + 2*faceW, 0, faceW, faceW);
  620.     make_projection(BOTTOM, sphereX, sphereY, sphereZ);
  621.     draw_scene(degrees, -1 & ~SPHERE_BIT);
  622.     glReadPixels(w + 2*faceW, 0, faceW, faceW, 
  623.          GL_RGBA, GL_UNSIGNED_BYTE, faceMap[BOTTOM]);
  624.     eliminate_alpha(faceW, faceW, faceMap[BOTTOM]);
  625.  
  626.     glViewport(w + 0*faceW, faceW, faceW, faceW);
  627.     make_projection(TOP, sphereX, sphereY, sphereZ);
  628.     draw_scene(degrees, -1 & ~SPHERE_BIT);
  629.     glReadPixels(w + 0*faceW, faceW, faceW, faceW, 
  630.          GL_RGBA, GL_UNSIGNED_BYTE, faceMap[TOP]);
  631.     eliminate_alpha(faceW, faceW, faceMap[TOP]);
  632.  
  633.     glViewport(w + 1*faceW, faceW, faceW, faceW);
  634.     make_projection(FRONT, sphereX, sphereY, sphereZ);
  635.     draw_scene(degrees, -1 & ~SPHERE_BIT);
  636.     glReadPixels(w + 1*faceW, faceW, faceW, faceW, 
  637.          GL_RGBA, GL_UNSIGNED_BYTE, faceMap[FRONT]);
  638.     eliminate_alpha(faceW, faceW, faceMap[FRONT]);
  639.  
  640.     glViewport(w + 2*faceW, faceW, faceW, faceW);
  641.     make_projection(BACK, sphereX, sphereY, sphereZ);
  642.     draw_scene(degrees, -1 & ~SPHERE_BIT);
  643.     glReadPixels(w + 2*faceW, faceW, faceW, faceW, 
  644.          GL_RGBA, GL_UNSIGNED_BYTE, faceMap[BACK]);
  645.     eliminate_alpha(faceW, faceW, faceMap[BACK]);
  646.  
  647.     /* create the sphere map for the cube... */
  648.     glViewport(w + sphereW, 2*faceW, sphereW, sphereW);
  649.     render_spheremap();
  650.     glReadPixels(w+sphereW, 2*faceW, sphereW, sphereW, 
  651.          GL_RGBA, GL_UNSIGNED_BYTE, sphereMap[1]);
  652.   }
  653.   frame = (frame == 0);
  654.  
  655.   /* draw both spheremaps */
  656.   glViewport(w, 2*faceW, 2*sphereW, sphereW);
  657.   glMatrixMode(GL_PROJECTION);
  658.   glLoadIdentity();
  659.   glOrtho(0, 2*sphereW, 0, sphereW, 0, 1);
  660.   glRasterPos2i(0, 0);
  661.   glDrawPixels(sphereW, sphereW, GL_RGBA, GL_UNSIGNED_BYTE, sphereMap[0]);
  662.   glRasterPos2i(sphereW, 0);
  663.   glDrawPixels(sphereW, sphereW, GL_RGBA, GL_UNSIGNED_BYTE, sphereMap[1]);
  664.  
  665.  
  666.     /* draw the scene for the viewer's visual gratification... */
  667.     glViewport(0, 0, w, h); 
  668.     glMatrixMode(GL_PROJECTION);
  669.     glLoadIdentity();
  670.     gluPerspective(60, 1, .01, 10);
  671.     gluLookAt(0, 0, 0, 
  672.           0, 0, -1, 
  673.           0, 1, 0);
  674.     glMatrixMode(GL_MODELVIEW);
  675.     glLoadIdentity();
  676.     glTranslatef(0, 0, -2.577);
  677.     draw_scene(degrees, -1);
  678.     glLoadIdentity();
  679.  
  680.     err = glGetError();
  681.     if (err != GL_NO_ERROR) printf("Error:  %s\n", gluErrorString(err));
  682.  
  683.     glutSwapBuffers();
  684. }
  685.  
  686. /* ARGSUSED1 */
  687. void key(unsigned char key, int x, int y)
  688. {
  689.   static int idle = 1;
  690.   switch(key) {
  691.   case 'a': case 'A':
  692.     animate = (animate == 0);
  693.     printf("%sanimating\n", animate ? "" : "not ");
  694.     break;
  695.   case 'd': case 'D':
  696.     printf("drawing\n");
  697.     draw();
  698.     break;
  699.   case 'r': case 'R':
  700.     printf("resetting sphere maps...\n");
  701.     reset_textures();
  702.     draw();
  703.     break;
  704.   case 't': case 'T':
  705.     useSphereMaps = (useSphereMaps == 0);
  706.     printf("%susing sphere maps\n", useSphereMaps ? "" : "not ");
  707.     break;
  708.   case 27:
  709.     exit(0);
  710.   default:
  711.     if (idle) {
  712.       glutIdleFunc(0);
  713.     } else {
  714.       glutIdleFunc(draw);
  715.     }
  716.     idle = (idle == 0);
  717.     printf("%sdrawing when idle\n", idle ? "" : "not ");
  718.     break;
  719.   }
  720. }
  721.  
  722. main(int argc, char *argv[])
  723. {
  724.     glutInitWindowSize(w*2, h);
  725.     glutInitWindowPosition(0, 0);
  726.     glutInit(&argc, argv);
  727.     glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
  728.     glutCreateWindow(argv[0]);
  729.     glutDisplayFunc(draw);
  730.     glutIdleFunc(draw);
  731.     glutKeyboardFunc(key);
  732.     glutReshapeFunc(reshape);
  733.     init(defaultFile);
  734.  
  735.     glutMainLoop();
  736.     return 0;
  737. }
  738.